home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 1997 November & December / Amiga-CD 1997 #11-12.iso / pd-disketten / ungepackt / 4_96 / apd-4-96-2 / gut gekurvt / drawbezier.cpp < prev    next >
C/C++ Source or Header  |  1996-03-13  |  5KB  |  188 lines

  1.  
  2. // Beispiel 3: Beziers zeichnen
  3. // Die eleganteste Möglichkeit, Béziers zu zeichnen ist:
  4. // Klicken und ziehen, um die Linie zu zeichnen, dann wieder Klicken und ziehen,
  5. // um jeweils einen Stützpunkt zu zeichnen.
  6.  
  7. #include <stdio.h>
  8. #include <exec/types.h>
  9. #include <intuition/intuition.h>
  10. #include <graphics/gfx.h>
  11. #include <graphics/rastport.h>
  12. #include <graphics/gfxmacros.h>
  13. #include <pragma/intuition_lib.h>
  14. #include <pragma/exec_lib.h>
  15. #include <pragma/graphics_lib.h>
  16. #include <time.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <math.h>
  20. #include <stream.h>
  21.  
  22.  
  23. double Bezier(struct RastPort *, double,double,double,double,double,double,double,double,double,int);
  24. void SetPoints(int status, int x,int y, 
  25.     double &k1x, double &k1y, double &k2x, double &k2y, double &k3x, double &k3y, double &k4x, double &k4y);
  26.  
  27.  
  28. struct Screen *scn = OpenScreenTags(NULL,
  29.             SA_Depth, 2,
  30.             SA_Width, 640,
  31.             SA_Height, 523,
  32.             SA_Quiet, TRUE,
  33.             SA_Type, CUSTOMSCREEN|AUTOSCROLL,
  34.             SA_DisplayID, PAL_MONITOR_ID|HIRESLACE_KEY,
  35.             TAG_END);
  36.  
  37. struct Window *win =  OpenWindowTags(NULL, 
  38.             WA_Flags, WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_DEPTHGADGET|WFLG_DRAGBAR|
  39.                          WFLG_NOCAREREFRESH|WFLG_SIMPLE_REFRESH|
  40.                          WFLG_DEPTHGADGET|WFLG_REPORTMOUSE,
  41.             WA_Top, 11,
  42.             WA_Width, 640,            WA_Height, 512,
  43.             WA_Left, 0,            
  44.             WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE,
  45.             WA_CustomScreen, scn,
  46.             WA_MouseQueue, 1,
  47.             WA_BlockPen, 4,            WA_DetailPen, 3,
  48.             WA_Title, "Bezier-Kurven",
  49.             TAG_END);
  50.  
  51. struct RastPort *rp = win->RPort;
  52.  
  53. char buf[255]; 
  54. int status = 0;
  55.  
  56. void main() {
  57.     if(!win || !scn) { CloseWindow(win); CloseScreen(scn); return };
  58.     try {
  59.         int mbpressed=FALSE, mmoved;
  60.         char buf[50];
  61.         int zaehler = 0;
  62.         int mcx, mcy;
  63.         double k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y;
  64.         while(1) {
  65.             // Mausabfrage auf die Hardcore-Art; heute: Message-Cracking, 
  66.             // Eigene Funktionen... doch hier nur ein Traum
  67.  
  68.             Wait(1 << win->UserPort->mp_SigBit);
  69.             struct IntuiMessage *imsg, icpy;
  70.             mmoved = FALSE;
  71.             while(imsg = (struct IntuiMessage*)GetMsg(win->UserPort)) {
  72.                 icpy = *imsg;
  73.                 ReplyMsg((struct Message*)imsg);
  74.                 mmoved = FALSE;
  75.                 switch(icpy.Class) {
  76.                     case IDCMP_CLOSEWINDOW:
  77.                         throw(int(1));        // kein guter Stil, aber einfach...
  78.                         break;
  79.                     case IDCMP_MOUSEBUTTONS:
  80.                         if(icpy.Code == SELECTDOWN) {
  81.                             mbpressed=TRUE;
  82.                             SetDrMd(rp,JAM2|COMPLEMENT);
  83.                             SetAPen(rp,2);
  84.                             if(status)
  85.                                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  86.                             SetPoints(status,icpy.MouseX,icpy.MouseY,
  87.                                             k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
  88.                             Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  89.                             sprintf(buf, "%1d (%3d,%3d),       Pressed", status, icpy.MouseX,icpy.MouseY);
  90.                             SetWindowTitles(win,buf,(STRPTR)-1);
  91.                             if(status<2) status++;
  92.                         } else if(icpy.Code == SELECTUP){
  93.                             mbpressed = FALSE; 
  94.                             Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  95.                             SetPoints(status,icpy.MouseX,icpy.MouseY,
  96.                                             k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
  97.                             Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  98.                             if(status == 3) {
  99.                                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  100.                                 SetDrMd(rp, JAM2);
  101.                                 SetAPen(rp, 1);
  102.                                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,100,0);
  103.                             }
  104.                             status=(status+1)%4;
  105.                                 
  106.                             sprintf(buf, "%1d (%3d,%3d),              ", status, icpy.MouseX,icpy.MouseY);
  107.                             SetWindowTitles(win,buf,(STRPTR)-1);
  108.                         }
  109.                         break;
  110.                     case IDCMP_MOUSEMOVE:
  111.                         mmoved = TRUE;
  112.                         mcx = icpy.MouseX;
  113.                         mcy = icpy.MouseY;
  114.                 }
  115.             }
  116.             if(mmoved && mbpressed) {
  117.                 sprintf(buf, "%1d (%3d,%3d), Moved Pressed", status, mcx,mcy);
  118.                 SetWindowTitles(win,buf,(STRPTR)-1);
  119.                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  120.                 SetPoints(status,mcx,mcy,
  121.                                 k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
  122.                 Bezier(rp,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y,25,1);
  123.                 
  124.             }                    
  125.         }
  126.     } catch(int n) {
  127.         if(n>1) cout << "Fehler "<< n << "\n";
  128.         CloseWindow(win); CloseScreen(scn); return; 
  129.     }
  130. }
  131.  
  132. void SetPoints(int status, int x, int y, 
  133.         double &k1x, double &k1y, double &k2x, double &k2y, double &k3x, double &k3y, double &k4x, double &k4y)
  134. {
  135.     switch(status) {
  136.         case 0:    // Erster Fixpunkt
  137.             k1x=k2x=k3x=k4x = x;
  138.             k1y=k2y=k3y=k4y = y;
  139.             break;
  140.         case 1:    // Zweiter Fixpunkt
  141.             k3x=k4x = x;
  142.             k3y=k4y = y;
  143.             break;
  144.         case 2:    // erster Kontrollpunkt
  145.             k2x=x;
  146.             k2y=y;
  147.             break;
  148.         case 3:    // zweiter
  149.             k3x=x;
  150.             k3y=y;
  151.             break;
  152.     }
  153.                     
  154.     sprintf(buf, "s: %d; (%3.1f,%3.1f),(%3.1f,%3.1f),(%3.1f,%3.1f),(%3.1f,%3.1f)",status,k1x,k1y,k2x,k2y,k3x,k3y,k4x,k4y);
  155.     SetWindowTitles(win, (STRPTR)-1, buf);
  156. }
  157.  
  158. struct Point {
  159.     int x;
  160.     int y;
  161. };
  162.  
  163. double Bezier(struct RastPort *rp, 
  164.     double k0x,double k0y,double k1x,double k1y,
  165.     double k2x,double k2y,double k3x,double k3y, double nr,int flag) 
  166. {
  167.     const double range = 
  168.         floor(10+(fabs(k0y-k1y)+fabs(k0x-k1x)+fabs(k1x-k2x)+
  169.                         fabs(k1y-k2y)+fabs(k2x-k3x)+fabs(k2y-k3y))/30.0);
  170.     const double step = 1.0/range;
  171.     double bx, by, emt, emt2, t2, tm3, emtm3;
  172.     const double rst = range*step;
  173.     
  174.     Move(rp,(long)k0x,(long)k0y);
  175.     
  176.     for(double t = step; t <= rst; t+= step) 
  177.     {
  178.         emt = 1-t; emt2=emt*emt; t2=t*t; tm3=3*t; emtm3 = 3*emt;
  179.         bx = emt2*(emt*k0x + tm3*k1x) + t2*(emtm3*k2x + t*k3x);
  180.         by = emt2*(emt*k0y + tm3*k1y) + t2*(emtm3*k2y + t*k3y);
  181.         Draw(rp,(long)bx,(long)by);
  182.     }
  183.     
  184.     return range;
  185. }
  186.  
  187.  
  188.